﻿
namespace Aeon.Emulator.Video
{
    /// <summary>
    /// Emulates the VGA Attribute Controller registers.
    /// </summary>
    internal sealed class AttributeController
    {
        #region Constructors
        /// <summary>
        /// Initializes a new instance of the AttributeController class.
        /// </summary>
        public AttributeController()
        {
            for(int i = 0; i < internalPalette.Length; i++)
                internalPalette[i] = (byte)i;
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Gets the internal palette.
        /// </summary>
        public byte[] InternalPalette
        {
            get { return internalPalette; }
        }
        /// <summary>
        /// Gets or sets the Attribute Mode Control register.
        /// </summary>
        public byte AttributeModeControl { get; set; }
        /// <summary>
        /// Gets or sets the Overscan Color register.
        /// </summary>
        public byte OverscanColor { get; set; }
        /// <summary>
        /// Gets or sets the Color Plane Enable register.
        /// </summary>
        public byte ColorPlaneEnable { get; set; }
        /// <summary>
        /// Gets or sets the Horizontal Pixel Panning register.
        /// </summary>
        public byte HorizontalPixelPanning { get; set; }
        /// <summary>
        /// Gets or sets the Color Select register.
        /// </summary>
        public byte ColorSelect { get; set; }
        #endregion

        #region Public Methods
        /// <summary>
        /// Returns the current value of an attribute controller register.
        /// </summary>
        /// <param name="address">Address of register to read.</param>
        /// <returns>Current value of the register.</returns>
        public byte ReadRegister(AttributeControllerRegister address)
        {
            if(address >= AttributeControllerRegister.FirstPaletteEntry && address <= AttributeControllerRegister.LastPaletteEntry)
                return InternalPalette[(byte)address];

            switch(address)
            {
            case AttributeControllerRegister.AttributeModeControl:
                return AttributeModeControl;

            case AttributeControllerRegister.OverscanColor:
                return OverscanColor;

            case AttributeControllerRegister.ColorPlaneEnable:
                return ColorPlaneEnable;

            case AttributeControllerRegister.HorizontalPixelPanning:
                return HorizontalPixelPanning;

            case AttributeControllerRegister.ColorSelect:
                return ColorSelect;

            default:
                return 0;
            }
        }
        /// <summary>
        /// Writes to an attribute controller register.
        /// </summary>
        /// <param name="address">Address of register to write.</param>
        /// <param name="value">Value to write to register.</param>
        public void WriteRegister(AttributeControllerRegister address, byte value)
        {
            if(address >= AttributeControllerRegister.FirstPaletteEntry && address <= AttributeControllerRegister.LastPaletteEntry)
                InternalPalette[(byte)address] = value;
            else
            {
                switch(address)
                {
                case AttributeControllerRegister.AttributeModeControl:
                    AttributeModeControl = value;
                    break;

                case AttributeControllerRegister.OverscanColor:
                    OverscanColor = value;
                    break;

                case AttributeControllerRegister.ColorPlaneEnable:
                    ColorPlaneEnable = value;
                    break;

                case AttributeControllerRegister.HorizontalPixelPanning:
                    HorizontalPixelPanning = value;
                    break;

                case AttributeControllerRegister.ColorSelect:
                    ColorSelect = value;
                    break;

                default:
                    break;
                }
            }
        }
        #endregion

        #region Private Fields
        private readonly byte[] internalPalette = new byte[16];
        #endregion
    }
}
